package cn.qayy.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cn.qayy.constants.Constant;
import cn.qayy.dao.BasisMapper;
import cn.qayy.dao.PlanMapper;
import cn.qayy.dto.CountryOver1k;
import cn.qayy.dto.Msg;
import cn.qayy.dto.PlanVo;
import cn.qayy.dto.PlansDTO;
import cn.qayy.dto.TaskDTO;
import cn.qayy.dto.TerminalOver1k;
import cn.qayy.dto.calsum;
import cn.qayy.po.Plan;
import cn.qayy.po.Policy;
import cn.qayy.po.Register;
import cn.qayy.po.Task;
import cn.qayy.service.IPlanLogService;
import cn.qayy.service.IPlanService;
import cn.qayy.service.IPolicyService;
import cn.qayy.service.IRegisterService;
import cn.qayy.service.SynchronizationService;
import cn.qayy.service.Uploadable;
import cn.qayy.utils.DownLoadUtil;
import cn.qayy.utils.InitPlansUtil;
import cn.qayy.utils.StringUtil;

/**
 * @author wangyu
 */
@Service("planServiceImpl")
public class PlanServiceImpl implements IPlanService {
	private Logger logger = LoggerFactory.getLogger(PlanServiceImpl.class);

	@Resource
	public PlanMapper planMapper;

	@Resource
	public BasisMapper basisMapper;
	
	@Resource(name = "policyServiceImpl")
	private IPolicyService policyService = null;

	@Resource(name = "synchronizationImpl")
	private SynchronizationService synchronizationService = null;
	
	@Resource(name = "registerServiceImpl")
	private IRegisterService registerService = null;
	
	@Resource(name = "planLogServiceImpl")
	private IPlanLogService planLogServiceImpl = null;
	
	@Override 
	public PageInfo<Map<String, Object>> selectPlanBy(Map<String, Object> params) throws Exception {
		if (params != null && params.size() > 0) {
			DownLoadUtil.set("PlansDTO",params);
			if (params.containsKey("pageNumber") && params.containsKey("pageSize")) {
				Integer pageNum = (Integer) params.get("pageNumber");
				Integer pageSize = (Integer) params.get("pageSize");
				PageHelper.startPage(pageNum, pageSize);
			}
			List<Map<String, Object>> list = planMapper.selectPlanBy(params);
			PageInfo<Map<String, Object>> pageInfo = new PageInfo<Map<String, Object>>(list);
			return pageInfo;
		}
		return null;
	}
	
	@Override
	public PageInfo<Plan> selectBy(PlanVo dto) throws Exception {
		/*if (dto != null) {
			DownLoadUtil.set("PlansDTO",dto);
			PageHelper.startPage(dto.getPageNumber(),dto.getPageSize());
			
			List<Plan> list = planMapper.selectBy(dto);
			PageInfo<Plan> pageInfo = new PageInfo<Plan>(list);
			return pageInfo;
		}*/
		return null;
	}

	@Override
	public List<Map<String, String>> selectGroup() {
		return planMapper.selectGroup();
	}

	@Override
	public int insertByList(List forList) {
		int ret = planMapper.insertByList(forList);
		logger.info("(insertByList)plan批量新增\n总记录数：" + forList.size() + "受影响行数：" + ret);
		return ret;
	}

	@Override
	public int updateByList(List forList) {
		int ret = planMapper.updateByList(forList);
		return ret;
	}

	@Override
	public int update(Object entity) {
		Plan plan = (Plan) entity;
		return planMapper.updateByPrimaryKeySelective(plan);
	}

	@Override
	public Plan selectPlanByID(@RequestParam Integer planId) {
		return planMapper.selectByPrimaryKey(planId);
	}

	// @Override
	public int addPlan(@RequestParam Map<String, Object> params) {
		Plan plan = new Plan();
		plan.setId(Integer.parseInt(String.valueOf(params.get("id"))));
		plan.setClient(params.get("client").toString());
		plan.setTerminal(params.get("terminal").toString());
		plan.setCommercial1(params.get("commercial1").toString());
		plan.setCount(params.get("count").toString());
		plan.setPihao(params.get("pihao").toString());
		plan.setSdate(params.get("sdate").toString());
		plan.setMoney6(params.get("money6").toString());
		plan.setStatus6(params.get("status6").toString());
		plan.setXieyizhuangtai(params.get("xieyizhuangtai").toString());
		plan.setProduct(params.get("product").toString());
		plan.setJudge(params.get("judge").toString());
		plan.setPack(params.get("pack").toString());
		plan.setMode(params.get("mode").toString());
		plan.setDemo(params.get("memo").toString());
		System.out.println("***:" + plan.toString());
		return planMapper.insertSelective(plan);
	}

	@Override
	public int deleteByList(List list) {
		int ret = planMapper.deleteByList(list);
		logger.info("(insertByList)plan批量删除\n总记录数：" + list.size() + "受影响行数：" + ret);
		return ret;
	}

	@Override
	public int insert(Object bean) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int delete(Object bean) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<String> findRealNaturalFlowKeys(Map<String, Object> params) {
		return planMapper.findRealNaturalFlowKeys(params);
	}

	public int updateStatus(Map<String, Object> statusMap) {
		return planMapper.updateStatus(statusMap);
	}

	@Override
	public int changeTerminal(Map<String, Object> keyMap) {
		int ret = 0;
		if (keyMap.get("type").equals("好伙伴")) {
			if (keyMap.get("revise").equals("E")) { // 修改
				ret = planMapper.updateGoodFriend(keyMap);
			} else if (keyMap.get("revise").equals("N")) { // 新增
				ret = planMapper.insertGoodFriend(keyMap);
			}
		} else if (keyMap.get("type").equals("重点终端")) {
			if (keyMap.get("revise").equals("E")) { // 修改
				ret = planMapper.updateImport(keyMap);
			} else if (keyMap.get("revise").equals("N")) { // 新增
				ret = planMapper.insertImport(keyMap);
			}
		}
		return ret;
	}

	@Override
	public List<Plan> selectByMap(Map<String, Object> params) throws Exception {
		return planMapper.selectByMap(params);
	}

	@Override
	public List<Map<String, Object>> selectGoodfriendByMap(Map<String, Object> params) throws Exception {
		return planMapper.selectGoodfriendByMap(params);
	}

	@Override
	public List<Map<String, Object>> selectFocusByMap(Map<String, Object> params) throws Exception {
		return planMapper.selectFocusByMap(params);
	}

	@Override
	public void updateOther(List<Plan> updateOtherYiFan) {
		planMapper.updateOther(updateOtherYiFan);
	}

	@Override
	public List<Plan> selectYifanKuCun(Map<String, Object> params) {
		return planMapper.selectYifanKuCun(params);
	}

	@Override
	public List<Plan> selectJiafanKuCun(Map<String, Object> params) {
		return planMapper.selectJiafanKuCun(params);
	}

	@Override
	public int updateByListNoLimit(List<Plan> list,HttpServletRequest request) throws Exception {
		request.setAttribute("logAction", "E");
		planLogServiceImpl.insertByList(list, request);
		int ret =  planMapper.updateByListNoLimit(list);
		return ret;
	}

	@Override
	public int deleteByIdList(List<String> idList) throws Exception {
		return planMapper.deleteByIdList(idList);
	}
	
	@Override
	public calsum selectSumBy(Map<String, Object> params) {
		
		return planMapper.selectSumBy(params);
	}

	@Override
	public List<Integer> selectIdsByMap(Map<String, Object> params) {
		return planMapper.selectIdsByMap(params);
	}

	@Override
	public List<CountryOver1k> selectCountryOver1k(Map<String, Object> params) {
		return planMapper.selectCountryOver1k(params);
	}

	@Override
	public List<TerminalOver1k> selectTerminalOver1k(Map<String, Object> params) {
		return planMapper.selectTerminalOver1k(params);
	}

	@Override
	public List<calsum> selectSumByMode(Map<String, Object> params) {
		return planMapper.selectSumByMode(params);
	}

	@Override
	public void persistence(Map<String, List<Uploadable>> map, HttpServletRequest request,
			HttpServletResponse response) throws Exception{
		
		// 待更新的实体list
		List<Uploadable> listE = map.get("E");
		if (listE != null && !listE.isEmpty()) {
			/** 待更新的实体list **/
			List<Plan> list = new ArrayList<Plan>(listE.size() + 1);
			/** 初始化流向 */
			List<Plan> okList = initPlans(list, listE, request);
			if (okList != null) {
				//插入日志
				request.setAttribute("logAction", "E");
				planLogServiceImpl.insertByList(list, request);
				
				// 修改,只能修改非毕流向
				planMapper.updateByList(list);
				
				//基础库同步更新流向，和基础库相关的数据都会同步更新流向。只有省份，更新时，只能更新非毕流向
				//InitPlansUtil.synchronizationPlan(synchronizationService, list);
			}
		}

		//删除
		List<Uploadable> listD = map.get("D");
		List<Integer> noDelList = new ArrayList<Integer>();
		if (listD != null && !listD.isEmpty()) {
			/** 待删除的实体list **/
			List<Plan> list = new ArrayList<Plan>(listD.size() + 1);
			List<Plan> db_list = new ArrayList<Plan>(listD.size()+1);
			List<String> ids = new ArrayList<String>(listD.size()+1);
			for (Uploadable u : listD) {
				PlansDTO dto = (PlansDTO)u;
				ids.add(dto.getId());
			}
			db_list = planMapper.selectByIds(ids);
			//校验Excel上传的id是否正确
			if(ids.size() != db_list.size()) {
				throw new Exception(Constant.FAIL_MSG_ID);
			}
			
			for (Uploadable u : listD) {
				PlansDTO dto = (PlansDTO) u;
				for(Plan p:db_list) {
					if(p.getId().toString().equals(dto.getId())) {
						boolean ok  = true;
						if(StringUtil.isNotBlank(p.getStatus1()) && p.getStatus1().contains("毕")) {
							ok = false;
						}
						if(StringUtil.isNotBlank(p.getStatus3()) && p.getStatus3().contains("毕")) {
							ok = false;
						}
						if(StringUtil.isNotBlank(p.getStatus4()) && p.getStatus4().contains("毕")) {
							ok = false;
						}
						if(StringUtil.isNotBlank(p.getStatus5()) && p.getStatus5().contains("毕")) {
							ok = false;
						}
						if(StringUtil.isNotBlank(p.getStatusMgr()) && p.getStatusMgr().contains("毕")) {
							ok = false;
						}
						if(ok) {
							list.add(p);
						} else {
							noDelList.add(p.getId());
						}
						continue;
					}
				}
			}
			if(!noDelList.isEmpty()) {
				Msg msg = new Msg(Constant.FAIL_CODE, "操作失败，有id存在【毕】的状态，无法删除，id：【"+noDelList.toString()+"】");
				throw new Exception(msg.toString());
			}
			
			if(!list.isEmpty() && noDelList.isEmpty()) {
				//插入日志
				request.setAttribute("logAction", "D");
				planLogServiceImpl.insertByList(list, request);
				// 删除。。。。
				planMapper.deleteByList(list);
			}
		}

		//新增
		List<Uploadable> listN = map.get("N");
		if (listN != null && !listN.isEmpty()) {
			/** 待新增的实体list **/
			List<Plan> list = new ArrayList<Plan>(listN.size() + 1);
			/** 初始化流向 */
			List<Plan> okList = initPlans(list, listN, request);
			if (okList != null) {
				// 新增。。。。
				planMapper.insertByList(list);
				
				//基础库同步更新流向，新增了某条流向，是否同步更新其他省地市
				//InitPlansUtil.synchronizationPlan(synchronizationService, list);
			}
		}
		
	}

	/***
	 * 初始化流向
	 * @param plans 初始化ok的流向
	 * @param list 批量导入已验证的流向
	 * @param request 请求
	 * @return null 表示初始化失败
	 * @throws Exception
	 */
	private List<Plan> initPlans(List<Plan> plans, List<Uploadable> list, HttpServletRequest request) throws Exception {
		/***
		 * 封装查询条件，为初始化流向作准备
		 */
		Set<String> cnames = new HashSet<String>(Constant.INIT_CAPACITY * 16);//入货乙方
		Set<String> products = new HashSet<String>(Constant.INIT_CAPACITY);//品种
		Set<String> packs = new HashSet<String>(Constant.INIT_CAPACITY);//包装
		Set<String> clinets = new HashSet<String>(Constant.INIT_CAPACITY * 16);//销售流向时，方可用到客户作为参数去查询协议
		Set<String> status = new HashSet<String>(Constant.INIT_CAPACITY * 16);//协议状态
		
		List<Plan> db_list = new ArrayList<Plan>(list.size()+1);
		List<String> ids = new ArrayList<String>(list.size()+1);
		//协议id
		List<String> pids = new ArrayList<String>(list.size()+1);
		//遍历上传的Excel文件对象
		for (Uploadable u : list) {
			PlansDTO dto = (PlansDTO) u;
			ids.add(dto.getId());
			/** 获取入货乙方、品种、包装、客户 **/
			if(StringUtil.isNotBlank(dto.getTerminal())) {
				cnames.add(dto.getTerminal());
			}
			if(StringUtil.isNotBlank(dto.getProduct())) {
				products.add(dto.getProduct());
			}
			if(StringUtil.isNotBlank(dto.getPack())) {
				packs.add(dto.getPack());
			}
			if(StringUtil.isNotBlank(dto.getClient())) {
				clinets.add(dto.getClient());
			}
		}
		//数据中的对象
		db_list = planMapper.selectByIds(ids);
		if(!db_list.isEmpty()) {
			for (Plan plan : db_list) {
				if(StringUtil.isNotBlank(plan.getClientpolicyId())) {
					pids.add(plan.getClientpolicyId());
				}
			}
		}
		//通过协议id，找到的协议
		List<Policy> idsGetPolicys = new ArrayList<Policy>();
		if(!pids.isEmpty()) {
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("ids",pids);
			idsGetPolicys = policyService.selectPolicys(params);//纯销的协议s
		}
		/***
		 * 获取所有相关的【注册库】数据对象
		 */
		Map<String, Object> params = new HashMap<String, Object>();//存放和纯销流向相关的参数
		Map<String, Object> params2 = new HashMap<String, Object>();//存放和销售流向相关的参数
		params.put("cnames", cnames);
		List<Register> registers = registerService.selectJiafanAndYifanByNames(params);

		/***
		 * 获取【协议相关】数据对象
		 */
		params.put("products", products);
		params.put("packs", packs);
		
		params2.put("products", products);
		params2.put("packs", packs);
		
		if(!clinets.isEmpty()) {
			params2.put("clinets", clinets);
		}
		//协议状态必须是有效状态
		status.add("4");
		status.add("5");
		status.add("6");
		
		params.put("status", status);
		params2.put("status", status);
		/***
		 * 【纯销流向】通过入货乙方+品种+包装+协议状态查询协议。
		 */
		List<Policy> policys = policyService.selectPolicys(params);//纯销的协议s
		/**
		 * 【销售流向】是按照客户+品种+包装查询协议的，故销售流向客户必须用户录入，不能期待系统自动匹配客户。
		 */
		List<Policy> xs_policys = policyService.selectPolicys(params2);//销售的协议s

		/** 真自然流的keys */
		Set<String> realNaturalFlowKeys = new HashSet<String>(Constant.SMALL_CAPACITY * 8);
		realNaturalFlowKeys.addAll(planMapper.findRealNaturalFlowKeys(params));
		
		//流向对应多个客户，批量提醒
		Set<String> manyClientMsg = new HashSet<String>();
		
		//遍历目标导入的流向，并初始化其相关属性
		for (Uploadable u : list) {
			PlansDTO dto = (PlansDTO) u;
			/***
			 * 封装数据
			 */
			Plan p = null;
			if("N".equals(dto.getIsUpdate())) {
				 p = new Plan();
			} else if ("E".equals(dto.getIsUpdate())) {
				for(Plan plan:db_list) {
					if(plan.getId().toString().equals(dto.getId())) {
						p = plan;
						continue;
					}
				}
			}
			/**1、封装模板属性 */
			p.setByDTO(dto);
			/**2、准备阶段的初始化*/
			InitPlansUtil.preparInit(p, request);
			/**3、注册库初始化流向 */
			InitPlansUtil.registerInit(registers, p);
			/**4、自动匹配客户，并初始化流向客户 **/
			List<String> isMoneyClients = InitPlansUtil.autoFindClient(policys, p);
			if (isMoneyClients != null && isMoneyClients.size() >= 2) {
				/***
				 * 前台提示失败信息
				 */
				Msg msg = new Msg(Constant.FAIL_CODE,
						"入货乙方：【"+p.getTerminal()+"】，"
								+ "品种：【"+p.getProduct()+"】，包装：【"+p.getPack()+"】");
				manyClientMsg.add(msg.toString());
			}
			/**5、初始化真自然流向 跟流向的客户、品种、包装、入货乙方有关系***/
			InitPlansUtil.realNaturalFlowKeys(realNaturalFlowKeys, p);
			/**6、协议初始化流向 */
			if("纯销".equals(p.getJudge()) || "销售".equals(p.getJudge()) || "另付".equals(p.getJudge())) {
				if("销售".equals(p.getJudge())) {
					if("QA".equals(p.getClient())) {
						InitPlansUtil.policyInitByPid(p,null);
					} else {
						if(StringUtil.isNotBlank(p.getClientpolicyId()) && !"0".equals(p.getClientpolicyId())) {
							//通过协议id匹配
							for(Policy po:idsGetPolicys) {
								if(p.getClientpolicyId().equals(po.getId().toString())) {
									InitPlansUtil.policyInitByPid(p,po);
									continue;
								}
							}
						} else {
							InitPlansUtil.policyInit(policys,xs_policys, p);
						}
					}
				} else {
					if("QA".equals(p.getClient())) {
						InitPlansUtil.policyInitByPid(p,null);
					} else {
						if(!"手动匹配政策".equals(p.getStatus7())) {
							InitPlansUtil.policyInit(policys,xs_policys, p);
						} else {
							//通过协议id匹配
							if(StringUtil.isNotBlank(p.getClientpolicyId()) && !"0".equals(p.getClientpolicyId())) {
								for(Policy po:idsGetPolicys) {
									if(p.getClientpolicyId().equals(po.getId().toString())) {
										InitPlansUtil.policyInitByPid(p,po);
										continue;
									}
								}
							} else {
								InitPlansUtil.policyInitByPid(p,null);
							}
						}
					}
				}
			} 
			/**7、初始化流向销售折量、生产折量，跟品种、包装、数量、条线有关系，必须明确条线后才能初始化 */
			InitPlansUtil.salesInit(p);
			/**8、初始化流向的其他属性 */
			InitPlansUtil.otherInit(p, request);
			plans.add(p);
		}
		
		if(!manyClientMsg.isEmpty()) {
			StringBuffer sb = new StringBuffer();
			for (String msg : manyClientMsg) {
				sb.append("<br/>"+msg);
			}
			plans=null;//发现异常放弃更新
			throw new Exception(sb.toString()+"，对应多个客户，请核查");
		}
		return plans;
	}

	@Override
	public int updateNomit(List<Plan> plans,HttpServletRequest request) throws Exception {
		//更新流向
		int doSize = updateByListNoLimit(plans,request);
		//基础库同步更新流向
		InitPlansUtil.synchronizationPlan(synchronizationService, plans);
		return doSize;
	}

}
